#!/usr/bin/perl
#
#
# Parse combat logs and pull all the data out
#
#
# In order to do this checking, this script will create and maintain
# entries in a mysql database. 
$database_name = "wfat";
$database_user = "wfat";
$database_host = "localhost";
$database_pwd = "c03lanth";
#
# Here's the CREATE sql on the database in case it should every die
# and go away...
#
# CREATE TABLE Records (
#         IPAddr VARCHAR(15) PRIMARY KEY NOT NULL,
#         LogTime DATETIME NOT NULL,
#         Occurences SMALLINT UNSIGNED NOT NULL
# );
# 
# use strict;
use DBI;
use Time::Local;
use Data::Dumper;
#
#
#
# Global
#
# Debug flag for lots more output and status
$DEBUG = 1;
#
#
# Connect to the database:
my $dbh = DBI->connect( "DBI:mysql:database=$database_name;host=", "$database_user", "$database_pwd" );

if ( !$dbh ) {
	die "Couldn't open database\n";
} else {
	# Database is open, continue
	if ( $DEBUG == 1 ) { print "Database open.\n"; }

	# Open up STDIN so we can read the file
	open( CMBTLOG, "-" ) or die "Couldn't open STDIN.\n"; 

	if ( $DEBUG == 1 ) { print "STDIN open.\n"; }

	$unique = 1;

	while ( <CMBTLOG> ) {
		# Our main read loop
		( $date, $time, $empty, $event ) = split( / /, $_, 4 );

		# Make a real time/datestamp
		( $month, $day ) = split( "/", $date );
		( $hour, $min, $second ) = split( ":", $time, 3 );
		( $sec, $msec ) = split( /\./, $second, 2 );

		# Figure out the current year. This will haev to do for now, but won't work for the long term
		( $blah, $blah, $blah, $blah, $blah, $year, $blah, $blah, $blah, $blah ) = localtime(time());

		# eventually, I'll need to probably work out something for dealing with
		# timezones here. But for now, ignore
		if ( $DEBUG == 2 ) {
			print "$date\n";
			print "\tmonth = $month\n";
			print "\tday = $day\n";
			print "\thour = $hour\n";
			print "\tmin = $min\n";
			print "\tsecond = $second\n";
			print "\tsec = $sec\n";
			print "\tmsec = $msec\n";
		}
		$datestamp = timelocal( $sec, $min, $hour, $day, $month, $year );
		if( $DEBUG == 2 ) { print "\tds = $datestamp\n"; }
		
		# Make a unique value using the split second
		$datestamp = $datestamp + ( $msec / 1000 ) + ( $unique / 10000 );
		if( $DEBUG == 2 ) { print "\tds = $datestamp\n"; }

		# Split out our whole message into bits.
		( $eventType, $srcGUID, $srcName, $srcFlags, $destGUID, $destName, $destFlags, $rest ) = split( /,/, $event, 8 );

		# store our values
		while ( exists $AllEvents{ $datestamp } ) {
			if ( $DEBUG == 2 ) { print "duplicate datestamp! $datestamp\n "; }
			$datestamp = $datestamp + ( $unique / 10000 );
		}
		if ( $DEBUG == 2 ) { print "Using datestamp = $datestamp\n"; }
		$AllEvents{ $datestamp }{ "Event" } = $eventType;
		$AllEvents{ $datestamp }{ "srcGUID" } = $srcGUID; 
		$AllEvents{ $datestamp }{ "srcName" } = $srcName; 
		$AllEvents{ $datestamp }{ "srcFlags" } = $srcFlags; 
		$AllEvents{ $datestamp }{ "destGUID" } = $destGUID; 
		$AllEvents{ $datestamp }{ "destName" } = $destName; 
		$AllEvents{ $datestamp }{ "destFlags" } = $destFlags; 
		$AllEvents{ $datestamp }{ "data" } = $rest;

		if ( $DEBUG == 2 ) {
			print "------------------------";
			print "$eventType:\n";
			print "\t$srcGUID\t\t$srcFlags\t$srcName\n";
			print "\t$destGUID\t\t$destFlags\t$destName\n";
			print "\t$rest\n";
		}
	}

	if ( $DEBUG == 1 ) { print "Done reading STDIN.\n"; }

	foreach $event ( sort keys %AllEvents ) {
		$srcGUID = $AllEvents{$event}{'srcGUID'};
		$srcName = $AllEvents{$event}{'srcName'};
		$srcFlags = hex( $AllEvents{$event}{'srcFlags'} );
		$destGUID = $AllEvents{$event}{'destGUID'};
		$destName = $AllEvents{$event}{'destName'};
		$destFlags = hex( $AllEvents{$event}{'destFlags'} );
		if ( $DEBUG == 2 ) { 
			print "eventid = $event\n";
			print "\t$srcName ($srcGUID)($srcFlags)\n";
			print "\t$destName ($destGUID)($destFlags)\n";
		}
		# Resolve our actors
		if ( not exists $Actors{$srcGUID} ) {
			# Found new src actor
			if ( $DEBUG == 2 ) { print "Found new actor : $srcName\n"; }
			$Actors{$srcGUID}{"Name"} = $srcName;
			$Actors{$srcGUID}{"Flags"}[0] = $srcFlags;
		} else {
			my $i = 0;
			my $found = 0;
			while ( ( $found == 0 ) && ( $Actors{$srcGUID}{"Flags"}[$i] != NULL ) ) {
				if ( $Actors{$srcGUID}{"Flags"}[$i] != $srcFlags ) {
					if ( $DEBUG == 2 ) { print "$srcGUID/$i/$Actors{$srcGUID}{'Flags'}[$i]\n"; }
					$i++;
				} else {
					$found = 1;
				}
			}
			if ( $found == 0 ) {
				$Actors{$srcGUID}{"Flags"}[$i] = $srcFlags;
			}
		}
		if ( not exists $Actors{$destGUID} ) {
			# Found new dest actor
			if ( $DEBUG == 2 ) { print "Found new actor : $destName\n"; }
			$Actors{$destGUID}{"Name"} = $destName;
			$Actors{$destGUID}{"Flags"}[0] = $destFlags;
		} else {
			my $i = 0;
			my $found = 0;
			while ( ( $found == 0 ) && ( exists $Actors{$destGUID}{"Flags"}[$i] ) ) {
				if ( $Actors{$destGUID}{"Flags"}[$i] != $destFlags ) {
					if ( $DEBUG == 2 ) { print "$destGUID/$i/$Actors{$destGUID}{'Flags'}[$i]\n"; }
					$i++;
				} else {
					$found = 1;
				}
			}
			if ( $found == 0 ) {
				$Actors{$destGUID}{"Flags"}[$i] = $destFlags;
			}
		}
	}

	# For each actor, determine the relationship to the primary actor
	foreach $GUID ( keys %Actors ) {
		# Blizzard constants for parsing flags:
		# Affiliation
		$COMBATLOG_OBJECT_AFFILIATION_MINE		= 0x00000001;
		$COMBATLOG_OBJECT_AFFILIATION_PARTY		= 0x00000002;
		$COMBATLOG_OBJECT_AFFILIATION_RAID		= 0x00000004;
		$COMBATLOG_OBJECT_AFFILIATION_OUTSIDER	= 0x00000008;
		$COMBATLOG_OBJECT_AFFILIATION_MASK		= 0x0000000F;
		# Reaction
		$COMBATLOG_OBJECT_REACTION_FRIENDLY		= 0x00000010;
		$COMBATLOG_OBJECT_REACTION_NEUTRAL		= 0x00000020;
		$COMBATLOG_OBJECT_REACTION_HOSTILE		= 0x00000040;
		$COMBATLOG_OBJECT_REACTION_MASK			= 0x000000F0;
		# Ownership
		$COMBATLOG_OBJECT_CONTROL_PLAYER		= 0x00000100;
		$COMBATLOG_OBJECT_CONTROL_NPC			= 0x00000200;
		$COMBATLOG_OBJECT_CONTROL_MASK			= 0x00000300;
		# Unit type
		$COMBATLOG_OBJECT_TYPE_PLAYER			= 0x00000400;
		$COMBATLOG_OBJECT_TYPE_NPC				= 0x00000800;
		$COMBATLOG_OBJECT_TYPE_PET				= 0x00001000;
		$COMBATLOG_OBJECT_TYPE_GUARDIAN			= 0x00002000;
		$COMBATLOG_OBJECT_TYPE_OBJECT			= 0x00004000;
		$COMBATLOG_OBJECT_TYPE_MASK				= 0x0000FC00;
		# Special cases (non-exclusive)
		$COMBATLOG_OBJECT_TARGET				= 0x00010000;
		$COMBATLOG_OBJECT_FOCUS					= 0x00020000;
		$COMBATLOG_OBJECT_MAINTANK				= 0x00040000;
		$COMBATLOG_OBJECT_MAINASSIST			= 0x00080000;
		$COMBATLOG_OBJECT_RAIDTARGET1			= 0x00100000;
		$COMBATLOG_OBJECT_RAIDTARGET2			= 0x00200000;
		$COMBATLOG_OBJECT_RAIDTARGET3			= 0x00400000;
		$COMBATLOG_OBJECT_RAIDTARGET4			= 0x00800000;
		$COMBATLOG_OBJECT_RAIDTARGET5			= 0x01000000;
		$COMBATLOG_OBJECT_RAIDTARGET6			= 0x02000000;
		$COMBATLOG_OBJECT_RAIDTARGET7			= 0x04000000;
		$COMBATLOG_OBJECT_RAIDTARGET8			= 0x08000000;
		$COMBATLOG_OBJECT_NONE					= 0x80000000;
		$COMBATLOG_OBJECT_SPECIAL_MASK			= 0xFFFF0000;

		$aName = $Actors{$GUID}{"Name"};
		if ( $DEBUG == 2 ) { print "$aName ($GUID)\n"; }
		$i = 0;
		while ( exists $Actors{$GUID}{"Flags"}[$i] ) {
			$aFlag = $Actors{$GUID}{"Flags"}[$i];
			if ( $DEBUG == 2 ) { print "\t$i ($aFlag)\n"; }
			my $flagStr = "";
			my $specialStr = "";

			# let's just go through one by one for now
			$Affiliation = $aFlag & $COMBATLOG_OBJECT_AFFILIATION_MASK;
			if ( $Affiliation == $COMBATLOG_OBJECT_AFFILIATION_MINE ) {
				$flagStr .= "MINE";
				$Actors{$GUID}{"IsPrimary"} = 1;
				$Actors{$GUID}{"IsGrouped"} = 0;
				if ( not exists $PrimaryActors{$GUID} ) { $PrimaryActors{$GUID} = 1; }
			} else {
				$Actors{$GUID}{"IsPrimary"} = 0;
				if ( $Affiliation == $COMBATLOG_OBJECT_AFFILIATION_PARTY ) {
					$flagStr .= "PARTY";
					$Actors{$GUID}{"IsGrouped"} = 1;
					if ( not exists $GroupedActors{$GUID} ) { $GroupedActors{$GUID} = 1; }
				} elsif ( $Affiliation == $COMBATLOG_OBJECT_AFFILIATION_RAID ) {
						$flagStr .= "RAID";
						$Actors{$GUID}{"IsGrouped"} = 1;
				} else {
						## OUTSIDER
 						$flagStr .= "OUTSIDER";
						$Actors{$GUID}{"IsGrouped"} = 0;
				}
			}

			$Reaction = $aFlag & $COMBATLOG_OBJECT_REACTION_MASK;
			if ( $Reaction == $COMBATLOG_OBJECT_REACTION_NEUTRAL ) {
				$flagStr .= " NEUTRAL";
				## If Reaction is already set, don't touch it.
				if ( not exists $Actors{$GUID}{"Reaction"} ) {
					$Actors{$GUID}{"Reaction"} = "NEUTRAL";
				}
			} elsif ( $Reaction == $COMBATLOG_OBJECT_REACTION_FRIENDLY ) {
				$flagStr .= " FRIENDLY";
				$Actors{$GUID}{"Reaction"} = "FRIENDLY";
			} else {
				$flagStr .= " HOSTILE";
				$Actors{$GUID}{"Reaction"} = "HOSTILE";
			}

			$Ownership	= $aFlag & $COMBATLOG_OBJECT_CONTROL_MASK;
			if ( $Ownership == $COMBATLOG_OBJECT_CONTROL_PLAYER ) {
				$flagStr .= " PLAYER";
				$Actors{$GUID}{"Owner"} = "PLAYER";
				if( not exists $Players{$GUID} ) { $Players{$GUID} = 1; }
			} else {
				# Objects like totems can go from "NPC -> PLAYER". If its already set, don't reset
				$flagStr .= " NPC";
				if ( not exists $Actors{$GUID}{"Owner"} ) {
					$Actors{$GUID}{"Owner"} = "NPC";
					if ( not exists $Mobs{$GUID} ) { $Mobs{$GUID} = 1; }
				}
			}

			$UnitType		= $aFlag & $COMBATLOG_OBJECT_TYPE_MASK;
			# Observed transitions
			#		NPC -> PET
			#		NPC -> GUARDIAN
			if ( $UnitType == $COMBATLOG_OBJECT_TYPE_PLAYER ) {
				$flagStr .= " PLAYER";
				$Actors{$GUID}{"UnitType"} = "PLAYER";
			} elsif ( $UnitType == $COMBATLOG_OBJECT_TYPE_NPC ) {
				$flagStr .= " NPC";
				if ( not exists $Actors{$GUID}{"UnitType"} ) {
					$Actors{$GUID}{"UnitType"} = "NPC";
				}
			} elsif ( $UnitType == $COMBATLOG_OBJECT_TYPE_PET ) {
				$flagStr .= " PET";
				$Actors{$GUID}{"UnitType"} = "PET";
			} elsif ( $UnitType == $COMBATLOG_OBJECT_TYPE_GUARDIAN ) {
				$flagStr .= " GUARDIAN";
				$Actors{$GUID}{"UnitType"} = "GUARDIAN";
			} else {
				# $UnitType == $COMBATLOG_OBJECT_TYPE_OBJECT
				$flagStr .= " OBJECT";
				$Actors{$GUID}{"UnitType"} = "OBJECT";
			}

			$specials = $aFlag & $COMBATLOG_OBJECT_SPECIAL_MASK;
			if ( $specials > 0 ) {
				## Special flags
				if ( $aFlag & $COMBATLOG_OBJECT_TARGET ) {
					$Actors{$GUID}{"Target"} = 1;
					$specialStr .= " TARGET";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_FOCUS ) {
					$Actors{$GUID}{"Focus"} = 1;
					$specialStr .= " FOCUS";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_MAINTANK ) {
					$Actors{$GUID}{"MainTank"} = 1;
					$specialStr .= " MAINTANK";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_MAINTASSIST ) {
					$Actors{$GUID}{"MainAssist"} = 1;
					$specialStr .= " MAINASSIST";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET1 ) {
					$Actors{$GUID}{"RaidTarget1"} = 1;
					$specialStr .= " RAIDTARGET1";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET2 ) {
					$Actors{$GUID}{"RaidTarget2"} = 1;
					$specialStr .= " RAIDTARGET2";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET2 ) {
					$Actors{$GUID}{"RaidTarget2"} = 1;
					$specialStr .= " RAIDTARGET2";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET3 ) {
					$Actors{$GUID}{"RaidTarget3"} = 1;
					$specialStr .= " RAIDTARGET3";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET4 ) {
					$Actors{$GUID}{"RaidTarget4"} = 1;
					$specialStr .= " RAIDTARGET4";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET5 ) {
					$Actors{$GUID}{"RaidTarget5"} = 1;
					$specialStr .= " RAIDTARGET5";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET6 ) {
					$Actors{$GUID}{"RaidTarget6"} = 1;
					$specialStr .= " RAIDTARGET6";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET7 ) {
					$Actors{$GUID}{"RaidTarget7"} = 1;
					$specialStr .= " RAIDTARGET7";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_RAIDTTARGET8 ) {
					$Actors{$GUID}{"RaidTarget8"} = 1;
					$specialStr .= " RAIDTARGET8";
				}
				if ( $aFlag & $COMBATLOG_OBJECT_NONE ) {
					$Actors{$GUID}{"None"} = 1;
					$specialStr .= " NONE";
				}
			}
			if ( $DEBUG == 2 ) {
				print "\t\tflags = $flagStr\n";
				if ( $specials > 0 ) { print "\t\tspecl = $specialStr\n"; }
			}
			$i++;
		}
	}
	
	# List the Primary Actors
	print "I found the following players that appear to be your characters,\n";
	foreach $GUID ( keys %PrimaryActors) {
		print "\t$Actors{$GUID}{'Name'} ($GUID)\n";
	}
		
	print "I found the following players that appear to have been grouped\n";
	print "with you, and should be included in the reporting:\n";
	foreach $GUID ( keys %GroupedActors) {
		print "\t$Actors{$GUID}{'Name'} ($GUID)\n";
	}

	# List off the people who are present around me that should be in the ignore list
	print "The following list is players that were around you while the log was taken,\n";
	print "but probably not directly involved in your combat, and will be ignored:\n";
	foreach $GUID ( keys %Players) {
		if ( exists $PrimaryActors{$GUID} ) {
			# Ignore. They're already listed above
		} elsif ( exists $GroupedActors{$GUID} ) {
			# Ignore. They're already listed above
		} else {
			print "\t$Actors{$GUID}{'Name'} ($GUID) ($Actors{$GUID}{'Reaction'})\n";
		}
	}


	# This is the place where the results of phase 1 (above) should be verified by the user
	# if thats going to happen.
	# Once verified, we can delete a whole mess of stuff.

	# Loop through all events again. As we're going through...
	# 	1) Prune all events not involving our actors.
	#	2) Start building our report/fight heirarchy.
	# 		A report is defined as one consecutive sequence of fights until a significant
	#		break in the log occurs (time-wise).
	#
	#		A "fight" is defined as a sequence of events where either all friendlies or
	#		all enemies die (or reset). I'm not sure yet if this will be easy to detect.
	#

	# Define an adjustable "ReportBreak". My current thinking is that this should be 1 hour.
	$ReportBreak = 3600;
	$MobRanAway = 120;

	# And some counters for our current report/fight
	$cReport = 0;
	$cFight = 0;
	$previousEvent = 0;
	foreach $EventID ( sort keys %AllEvents ) {

		# Assign some temporary variables so things are easier to reference:
		$event = $AllEvents{$EventID}{"Event"};
		$srcGUID = $AllEvents{$EventID}{"srcGUID"};
		$destGUID = $AllEvents{$EventID}{"destGUID"};

		# Have we had a significant break in the action? (New Report?)
		if ( $previousEvent != 0 ) {
			if ( ( $EventID - $previousEvent ) > $ReportBreak ) {
				if ( $DEBUG == 1 ) { print "event is $EventID, pEvent is $previousEvent > $ReportBreak.\n"; }
				$cReport++;
				$cFight = 0;
			}
		}
		$previousEvent = $EventID;

		# First, check to see if the event involves one of the actors we care about
		if ( ( exists $PrimaryActors{ $srcGUID } ) ||
			 ( exists $PrimaryActors{ $destGUID } ) ||
			 ( exists $GroupedActors{ $srcGUID } ) ||
			 ( exists $GroupedActors{ $destGUID } ) ||
			 ( $srcGUID eq "0x0000000000000000" ) ||
			 ( $destGUID eq "0x0000000000000000" ) ) {

			# This event matters
			$GoodEvents{$cReport}{$cFight} = $AllEvents{$EventID};
			$CheckForNewFight = 0;

			if ( $DEBUG == 2 ) {
				print "\tevent = $event\n";
				print "\tsrc   = $srcGUID\n";
				print "\tdest  = $destGUID\n";
			}

			# Is this a death event?
			if ( ( $event eq "UNIT_DIED" ) || ( $event eq "PARTY_KILL") ) {


				if ( $event eq "PARTY_KILL" ) {
					# Ignore PARTY_KILL for now. We'll come back and deal with killing blows later
					if ( $DEBUG == 2 ) { print "\t\tIgnoring party kill (for now).\n"; }
				} else {
					# UNIT_DIED always have a zero actor for src_GUID. However, the actors *should*
					# already be in my table if they were supposed to be. So check, and mark 'em
					# dead if they're in my table. If not, ignore
					if ( exists $FightActors[$cReport][$cFight]{ $destGUID } ) {
						# Mark it dead.
						$FightActors[$cReport][$cFight]{ $destGUID }{"State"} = "DEAD";
						if ( $DEBUG == 1 ) { print "\t\tMarking $destGUID dead.\n"; }
	
						# We killed something. We need to check if this fight is over
						$CheckForNewFight = 1;
					} else {
						# Somebody died who isn't in this current fight table. Ignore it I guess.
						if ( $DEBUG == 2 ) { print "\t\tOut of fight actor died ($destGUID).\n"; }
					}
				}
			} else {
				# It sometimes occurs that you'll get a damage message for a mob that just died in the last
				# fight. We don't want to start a new fight, or add the mob again in the new fight, so check
				# for that, and ignore if its true
				if (
				    ( $cFight > 1 ) &&
					(
					 (
					  ( exists $FightActors[$cReport][$cFight - 1]{ $destGUID } ) && 
					  ( $FightActors[$cReport][$cFight - 1]{ $destGUID }{"State"} eq "DEAD" )
					 ) ||
					 (
					  ( exists $FightActors[$cReport][$cFight - 1]{ $srcGUID }  ) && 
					  ( $FightActors[$cReport][$cFight - 1]{ $srcGUID }{"State"} eq "DEAD" )
					 )
					)
				   ) {
					# The actor was in the last fight, and died, ignoring
						if ( $DEBUG == 1 ) { print "\t\tActor died in last fight, ignoring.\n"; }
				} else {
					# Make sure our src and dest actors exist in our current fight table. If it doesn't, add it in.
			
					# src
					if ( not exists $FightActors[$cReport][$cFight]{ $srcGUID } ) {
						# The actor "0" is a special case, should always be considered FRIENDLY and ALIVE
						if ( $srcGUID eq "0x0000000000000000" ) {
							$FightActors[$cReport][$cFight]{ $srcGUID }{"State"} = "ALIVE";
							$FightActors[$cReport][$cFight]{ $srcGUID }{"React"} = "FRIENDLY";
							$FightActors[$cReport][$cFight]{ $srcGUID }{"lastAct"} = $EventID;
							if ( $DEBUG == 1 ) { print "\t\tAdding zero actor\n"; }
						} else {
							# If this source actor is acting ON destGUID of 0, don't add him in
							if ( $destGUID ne "0x0000000000000000" ) {
								$FightActors[$cReport][$cFight]{ $srcGUID }{"State"} = "ALIVE";
								if ( ( exists $PrimaryActors{ $srcGUID } ) || ( exists $GroupedActors{ $srcGUID } ) ) {
									if ( $DEBUG == 1 ) { print "\t\tAdding (F) $srcGUID to $cReport/$cFight\n"; }
									$FightActors[$cReport][$cFight]{ $srcGUID }{"React"} = "FRIENDLY";
									$FightActors[$cReport][$cFight]{ $srcGUID }{"lastAct"} = $EventID;
								} elsif ( $Actors{ $srcGUID }{"Reaction"} eq "FRIENDLY" ) {
									# Sometimes just a random passerby will toss us a heal or something
									if ( $DEBUG == 1 ) { print "\t\tAdding (F) $srcGUID (not partied) to $cReport/$cFight\n"; }
									$FightActors[$cReport][$cFight]{ $srcGUID }{"React"} = "FRIENDLY";
									$FightActors[$cReport][$cFight]{ $srcGUID }{"lastAct"} = $EventID;
								} else  {
									if ( $DEBUG == 1 ) { print "\t\tAdding (H) $srcGUID to $cReport/$cFight\n"; }
									$FightActors[$cReport][$cFight]{ $srcGUID }{"React"} = "HOSTILE";
									$FightActors[$cReport][$cFight]{ $srcGUID }{"lastAct"} = $EventID;
								}
						} else {
								if ( $DEBUG == 2 ) { print "\t\tdestGUID is 0, ignoring.\n"; }
							}
						}
					} else {
						# Reference already exists. gtg.
	   				}
	
					# dest
					if ( not exists $FightActors[$cReport][$cFight]{ $destGUID } ) {
						# The actor "0" is a special case, should always be considered FRIENDLY and ALIVE
						if ( $destGUID eq "0x0000000000000000" ) {
							$FightActors[$cReport][$cFight]{ $destGUID }{"State"} = "ALIVE";
							$FightActors[$cReport][$cFight]{ $destGUID }{"React"} = "FRIENDLY";
							$FightActors[$cReport][$cFight]{ $destGUID }{"lastAct"} = $EventID;
							if ( $DEBUG == 1 ) { print "\t\tAdding zero actor\n"; }
						} else {
							# If this dest actor is being acted on by a srcGUID of 0, don't add
							if ( $srcGUID ne "0x0000000000000000" ) {
								$FightActors[$cReport][$cFight]{ $destGUID }{"State"} = "ALIVE";
								if ( ( exists $PrimaryActors{ $destGUID } ) || ( exists $GroupedActors{ $destGUID } ) ) {
									if ( $DEBUG == 1 ) { print "\t\tAdding (F) $destGUID to $cReport/$cFight\n"; }
									$FightActors[$cReport][$cFight]{ $destGUID }{"React"} = "FRIENDLY";
									$FightActors[$cReport][$cFight]{ $destGUID }{"lastAct"} = $EventID;
								} elsif ( $Actors{ $destGUID }{"Reaction"} eq "FRIENDLY" ) {
									# Sometimes we toss a spell to a random passerby
									if ( $DEBUG == 1 ) { print "\t\tAdding (F) $destGUID (not partied) to $cReport/$cFight\n"; }
									$FightActors[$cReport][$cFight]{ $destGUID }{"React"} = "FRIENDLY";
									$FightActors[$cReport][$cFight]{ $destGUID }{"lastAct"} = $EventID;
								} else {
									if ( $DEBUG == 1 ) { print "\t\tAdding (H) $destGUID to $cReport/$cFight\n"; }
									$FightActors[$cReport][$cFight]{ $destGUID }{"React"} = "HOSTILE";
									$FightActors[$cReport][$cFight]{ $destGUID }{"lastAct"} = $EventID;
								}
							} else {
								if ( $DEBUG == 2 ) { print "\t\tsrcGUID is 0, ignoring.\n"; }
							}
						}
					} else {
						# Reference already exists. gtg.
					}
				}
			}

			if ( $CheckForNewFight == 1 ) {

				# This implies someone died. Check to see if all our friendlies or all our hostiles are
				# dead.
				$FriendliesAlive = 0;
				$HostilesAlive = 0;
				foreach $GUID ( keys %{ $FightActors[$cReport][$cFight] } ) {

					$FAstate = $FightActors[$cReport][$cFight]{ $GUID }{"State"};
					$FAreact = $FightActors[$cReport][$cFight]{ $GUID }{"React"};
					$FAlastAct = $FightActors[$cReport][$cFight]{ $GUID }{"lastAct"};

					if ( $DEBUG == 1 ) { print "($GUID) - $FAstate / $FAreact ($FAlastAct)\n"; }

					# Also, check through the Hostiles. If any of them haven't had any activity in
					# $MobRanAway, assume they've run off, and remove them
					if ( $FAreact eq "FRIENDLY" ) {
						if ( $FAstate eq "ALIVE" ) { $FriendliesAlive++; }
					} else {
						if ( ( $EventID - $FAlastAct ) >= $MobRanAway ) {
							if ( $DEBUG == 1 ) { print "\t\tAssuming $GUID ran away.\n"; }
							delete $FightActors[$cReport][$cFight]{ $GUID };
						} else {
							if ( $FAstate eq "ALIVE" ) { $HostilesAlive++; }
						}
					}
				}
				if ( ( $FriendliesAlive == 0 ) || ( $HostilesAlive == 0 ) ) {
					if ( $DEBUG == 1 ) { print "New fight.\n"; }
					$cFight++;
				}
			}
		} else {
			# Don't do anything. This event won't go into our report/fight event hashes
			if ( $DEBUG == 2 ) { print "This event doesn't involve our concerned actors. Ignoring\n"; }
		}
	}

	# Two things will determine the spans of two to generate reports on
	# First, the presence of the primary actors
	# Second, breaks in the spans of time.



	# $sth = $dbh->prepare( "SELECT * FROM Records WHERE IPAddr='$ipaddress'" );
   	# $numrows = $sth->execute();
	# $row = $sth->fetchrow_hashref();
	# $ipaddr = $row[ 'IPAddr' ];
}
$dbh->disconnect();
if ( $DEBUG == 1 ) { print "Disconnecting from Database.\n"; }
